﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace UBCon.Controls
{
    public class EllipticalProgressBar : ProgressBarBase
    {
        #region Constructors

        public EllipticalProgressBar()
        {
            startTimer.Interval = TimeSpan.FromMilliseconds(800);
            startTimer.Tick += startTimer_Tick;
        }

        private void startTimer_Tick(object sender, EventArgs e)
        {
            startTimer.Stop();

            for (int i = 0; i < ItemsCount; i++)
            {
                SimplaAnimations[i].Begin();
            }
        }

        #endregion

        #region Properties

        public static double GetAngle(DependencyObject obj)
        {
            return (double)obj.GetValue(AngleProperty);
        }

        internal static void SetAngle(DependencyObject obj, double value)
        {
            obj.SetValue(AngleProperty, value);
        }

        // Using a DependencyProperty as the backing store for Angle.  This enables animation, styling, binding, etc...
        internal static readonly DependencyProperty AngleProperty =
            DependencyProperty.RegisterAttached("Angle", typeof(double), typeof(EllipticalProgressBar), new PropertyMetadata(-160.0, new PropertyChangedCallback(OnAnglePropertyChanged)));

        #endregion

        #region Depenency Property Changed Callbacks

   
        private static void OnAnglePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            double angle = (double)e.NewValue;
            FrameworkElement shape = sender as FrameworkElement;
            TranslateTransform translate = shape.RenderTransform as TranslateTransform;
            angle = angle * radian;
            translate.X = XRadius * (1 + Math.Cos(angle));
            translate.Y = (1 - Math.Sin(angle)) * YRadius;
            //progerss.UpdateAngle(angle);
        }

        #endregion

        #region Overrides
       
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            XRadius = sizeInfo.NewSize.Width / 2;
            YRadius = sizeInfo.NewSize.Height / 2;
            StartAnimation();
            base.OnRenderSizeChanged(sizeInfo);
        }

        #endregion

        #region Private Utilities

        private void UpdateAngle(double angle)
        {
            TranslateTransform translate = Items[0].RenderTransform as TranslateTransform;
            angle = angle * radian;
            translate.X = XRadius * (1 + Math.Cos(angle));
            translate.Y = (1 - Math.Sin(angle)) * YRadius;
        }

        protected override void BuildSimpleAnimation()
        {
            if (SimplaAnimations.Count > 0)
            {
                for (int i = 0; i < ItemsCount; i++)
                {
                    SimplaAnimations[i].Stop();

                    SimplaAnimations[i].Children.Clear();
                }

                SimplaAnimations[4].Completed -= simpleAnimation_Completed;
            }

            SimplaAnimations.Clear();

            for (int i = 0; i < ItemsCount; i++)
            {
                simpleAnimation = new Storyboard() { AutoReverse = false };

                simpleAnimation.BeginTime = TimeSpan.FromMilliseconds(i * 200);
                DoubleAnimation da = new DoubleAnimation();
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(EllipticalProgressBar.AngleProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(0.8));
                da.To = -270 + i * Distance;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(0.1);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(Ellipse.OpacityProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(0.2));
                da.To = 1.0;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(0.8);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(EllipticalProgressBar.AngleProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(0.7));
                da.To = -320 + i * Distance;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(1.5);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(EllipticalProgressBar.AngleProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(.7));
                //                da.Duration = new Duration(TimeSpan.FromSeconds(.8 - i * 0.1));
                da.To = -590 + i * Distance;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(2.2);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(EllipticalProgressBar.AngleProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(1.0));
                da.To = -680 + i * Distance;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(3.2);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(EllipticalProgressBar.AngleProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(.3));
                da.To = -810;

                da = new DoubleAnimation();
                da.BeginTime = TimeSpan.FromSeconds(3.4);
                Storyboard.SetTarget(da, Items[i]);
                Storyboard.SetTargetProperty(da, new PropertyPath(Ellipse.OpacityProperty));
                simpleAnimation.Children.Add(da);
                da.Duration = new Duration(TimeSpan.FromSeconds(0.1));
                da.To = 0.0D;

                SimplaAnimations.Add(simpleAnimation);
            }
            SimplaAnimations[4].Completed += simpleAnimation_Completed;

        }

        void simpleAnimation_Completed(object sender, EventArgs e)
        {
            for (int i = 0; i < ItemsCount; i++)
            {
                Items[i].ApplyAnimationClock(EllipticalProgressBar.AngleProperty, null);
                Items[i].SetValue(EllipticalProgressBar.AngleProperty, -90.0D);
            }
            startTimer.Start();
        }

        protected override void InitializeItems()
        {
            for (int i = 0; i < ItemsCount; i++)
            {
                Ellipse ellipse = new Ellipse() { HorizontalAlignment = System.Windows.HorizontalAlignment.Left, VerticalAlignment = System.Windows.VerticalAlignment.Top, Opacity = 0.0D };
                BindingOperations.SetBinding
                    (
                        ellipse,
                        Ellipse.WidthProperty,
                        new Binding("ItemSize") { Source = this, Mode = BindingMode.OneWay, NotifyOnSourceUpdated = true }
                    );

                BindingOperations.SetBinding
                    (
                        ellipse,
                        Ellipse.HeightProperty,
                        new Binding("ItemSize") { Source = this, Mode = BindingMode.OneWay, NotifyOnSourceUpdated = true }
                    );
                BindingOperations.SetBinding
                    (
                        ellipse,
                        Ellipse.FillProperty,
                        new Binding("Color") { Source = this, Mode = BindingMode.OneWay, NotifyOnSourceUpdated = true }
                    );
                ellipse.RenderTransform = new TranslateTransform();
                ellipse.SetValue(EllipticalProgressBar.AngleProperty, -85.0D);

                Items.Add(ellipse);
            }
        }

        #endregion

        #region Event Handlers

        #endregion

        #region Fields
        
        private static double XRadius, YRadius;
        private const double radian = Math.PI / 180.0D;

        #endregion

        #region Events
        #endregion

    }
}
